package loupan

import (
	"errors"
	"fmt"
	database "hft/Database"
	"hft/Database/admin"
	"hft/Http/Models/dao"
	"hft/Http/Models/request"
	"hft/Http/Services/base"
	"hft/Http/Services/loupan/loupan_dao"
	"hft/Http/Services/loupan/loupan_model"
	utils "hft/Http/Utils"
	"hft/e"
	"hft/global"
	"hft/tools"
	"regexp"
	"strconv"
	"strings"

	"gorm.io/gorm"
)

type LouPan struct{}

func (*LouPan) CreateLouPan(LouPanInfo *request.LouPan, claims tools.BaseClaims) (err error) {
	var region *admin.Region
	account, err := base.FindAccount(claims, global.OC_DB)
	if err != nil {
		return errors.New(e.AccountNotExist)
	}
	err = global.OC_DB.First(&region, LouPanInfo.Region).Error
	if err != nil {
		return errors.New(e.RegionNotFound)
	}
	if err = loupan_dao.CanThisAccountAddLouPanInThisRegion(account.RegionLink, region.Link); err != nil {
		return err
	}
	belongName := utils.AccountBelongRegion(fmt.Sprintf("%v%v,", region.Link, region.ID), global.OC_DB)
	tags, dis, property, roomType, tese := loupan_dao.FindLouPreloadDao(global.OC_DB, LouPanInfo)
	err = global.OC_DB.Transaction(func(tx *gorm.DB) error {
		dn := loupan_dao.SelectMaxID(tx) //最大手机号
		fmt.Println(dn, "分机号")
		var louPan = &admin.LouPan{
			Base:             database.Base{Sort: LouPanInfo.Sort},
			FirstWord:        tools.PinYin(LouPanInfo.Name),
			MaxArea:          LouPanInfo.MaxArea,
			MinArea:          LouPanInfo.MinArea,
			Name:             LouPanInfo.Name,
			Cover:            LouPanInfo.Cover,
			RegionLink:       fmt.Sprintf("%v%v,", region.Link, LouPanInfo.Region),
			Region:           LouPanInfo.Region,
			BelongName:       belongName,
			Years:            LouPanInfo.Years,
			Furnish:          LouPanInfo.Furnish,
			Address:          LouPanInfo.Address,
			ReferencePrice:   LouPanInfo.ReferencePrice,
			Grounding:        LouPanInfo.Grounding,
			Longitude:        LouPanInfo.Longitude,
			Latitude:         LouPanInfo.Latitude,
			IsAudit:          0,
			Status:           LouPanInfo.Status,
			ActiveLastUpdate: 0,
			SellLouPanInfo: admin.SellLouPanInfo{
				OpenTime:    LouPanInfo.OpenTime,
				GetRoomTime: LouPanInfo.GetRoomTime,
				Developer:   LouPanInfo.Developer,
				License:     LouPanInfo.License,
				SellPhone:   strconv.Itoa(dn),
			},
			LouPanArea: admin.LouPanArea{
				FloorArea:       LouPanInfo.FloorArea,
				BuildArea:       LouPanInfo.BuildArea,
				BuildNum:        LouPanInfo.BuildNum,
				UserNum:         LouPanInfo.UserNum,
				ParkingSpace:    LouPanInfo.ParkingSpace,
				VolumeRate:      LouPanInfo.VolumeRate,
				GreeningRate:    LouPanInfo.GreeningRate,
				PropertyCost:    LouPanInfo.PropertyCost,
				PropertyCompany: LouPanInfo.PropertyCompany,
			},
		}
		var result *loupan_model.Result
		if res := tx.Where("name = ? AND region = ?", louPan.Name, louPan.Region).FirstOrCreate(&louPan).Scan(&result); res.Error != nil {
			return errors.New(e.ErrorInfo)
		} else if res.RowsAffected == 0 {
			return errors.New(e.LouPanHasExist)
		}
		var managerPhone string
		// 如果当前操作者不是站长，则改为总站长的手机号码
		fmt.Println(account.Phone, account.Username, account.RealName, account.RoleId)
		if account.RoleId != 32 {
			// 找出楼盘所在的城市
			var strArr = strings.Split(region.Link, ",")
			manager_city, _ := strconv.Atoi(strArr[3])
			fmt.Println(manager_city, "城市")
			// 找出管理员
			var manager_region *admin.Region
			tx.Select("id, manage_id, over_time, name").First(&manager_region, manager_city)
			fmt.Println("管理城市", manager_region.Name, manager_region.ManageId)
			if manager_region.ManageId != 0 {
				var manager_account *admin.Account //当前管理人员
				tx.Select("id, phone").First(&manager_account, manager_region.ManageId)
				fmt.Println("城市:", manager_region.Name, " 管理者:", manager_account.Phone)
				managerPhone = manager_account.Phone
			} else {
				managerPhone = account.Phone
			}
		} else {
			managerPhone = account.Phone
		}
		if err = loupan_dao.AddPhoneConfigToLouPan(tx, LouPanInfo.Name, result.ID, managerPhone, dn); err != nil {
			return err
		}
		loupan_dao.ReplaceLouPreloadDao(tx, louPan, tags, dis, property, roomType, tese)
		// 创建二维码
		loupan_dao.CreateLouPanQrCode(tx, int(result.ID))
		return nil
	})
	return err
}

func (*LouPan) GetLouPanList(paginate *request.LouPaPaginate, claims tools.BaseClaims) (data *utils.Page, err error) {

	var louPanList []*admin.LouPan
	account, err := base.FindAccount(claims, global.OC_DB)
	if err != nil {
		return nil, errors.New(e.AccountNotExist)
	}
	err = global.OC_DB.Scopes(dao.LouPanDao.GetLouPanList(fmt.Sprintf("%v%%", account.RegionLink), paginate, global.OC_DB)).Find(&louPanList).Offset(-1).Limit(-1).Count(&paginate.Total).Error
	if err != nil {
		return nil, errors.New(e.ErrorInfo)
	}
	for _, v := range louPanList {
		v.Cover = global.OC_CONFIG.AliyunOSS.BucketUrl + v.Cover
		v.SellLouPanInfo.SellPhone = global.OC_CONFIG.Phone.Account + "," + v.SellLouPanInfo.SellPhone
		if len(v.Disadvantage) != 0 {
			for _, j := range v.Disadvantage {
				j.Cover = global.OC_CONFIG.AliyunOSS.BucketUrl + j.Cover
			}
		}
	}
	paginate.Data = louPanList
	return &paginate.Page, nil
}

func (*LouPan) EditLouPan(LouPanInfo *request.LouPan, claims tools.BaseClaims) (err error) {
	var region *admin.Region
	account, err := base.FindAccount(claims, global.OC_DB)
	if err != nil {
		return errors.New(e.AccountNotExist)
	}
	if err = global.OC_DB.First(&region, LouPanInfo.Region).Error; err != nil {
		return errors.New(e.RegionNotFound)
	}
	if err = loupan_dao.CanThisAccountAddLouPanInThisRegion(account.RegionLink, region.Link); err != nil {
		return err
	}
	belongName := utils.AccountBelongRegion(fmt.Sprintf("%v%v,", region.Link, region.ID), global.OC_DB)
	tags, dis, property, roomType, tese := loupan_dao.FindLouPreloadDao(global.OC_DB, LouPanInfo)
	err = global.OC_DB.Transaction(func(tx *gorm.DB) error {

		var louPan = &admin.LouPan{
			Base: database.Base{
				ID:   uint(LouPanInfo.ID),
				Sort: LouPanInfo.Sort,
			},
			FirstWord:      tools.PinYin(LouPanInfo.Name),
			MaxArea:        LouPanInfo.MaxArea,
			MinArea:        LouPanInfo.MinArea,
			Name:           LouPanInfo.Name,
			Cover:          LouPanInfo.Cover,
			RegionLink:     fmt.Sprintf("%v%v,", region.Link, LouPanInfo.Region),
			Region:         LouPanInfo.Region,
			BelongName:     belongName,
			Years:          LouPanInfo.Years,
			Address:        LouPanInfo.Address,
			Furnish:        LouPanInfo.Furnish,
			ReferencePrice: LouPanInfo.ReferencePrice,
			Grounding:      LouPanInfo.Grounding,
			Longitude:      LouPanInfo.Longitude,
			Latitude:       LouPanInfo.Latitude,
			IsAudit:        0,
			Status:         LouPanInfo.Status,
		}
		if res := tx.Where("id = ?", LouPanInfo.ID).Updates(&louPan); res.Error != nil {
			return errors.New(e.ErrorInfo)
		}
		tx.Model(&admin.LouPan{}).Where("id = ?", LouPanInfo.ID).Updates(map[string]interface{}{"grounding": LouPanInfo.Grounding})
		tx.Model(&admin.SellLouPanInfo{}).Where("lou_pan_id = ?", LouPanInfo.ID).Updates(admin.SellLouPanInfo{
			OpenTime:    LouPanInfo.OpenTime,
			GetRoomTime: LouPanInfo.GetRoomTime,
			Developer:   LouPanInfo.Developer,
			License:     LouPanInfo.License,
		})
		tx.Model(&admin.LouPanArea{}).Where("lou_pan_id = ?", LouPanInfo.ID).Updates(admin.LouPanArea{
			FloorArea:       LouPanInfo.FloorArea,
			BuildArea:       LouPanInfo.BuildArea,
			BuildNum:        LouPanInfo.BuildNum,
			UserNum:         LouPanInfo.UserNum,
			ParkingSpace:    LouPanInfo.ParkingSpace,
			VolumeRate:      LouPanInfo.VolumeRate,
			GreeningRate:    LouPanInfo.GreeningRate,
			PropertyCost:    LouPanInfo.PropertyCost,
			PropertyCompany: LouPanInfo.PropertyCompany,
		})
		loupan_dao.ReplaceLouPreloadDao(tx, louPan, tags, dis, property, roomType, tese)
		return nil
	})

	return nil
}

func (*LouPan) GetLouPanInfo(id int, claims tools.BaseClaims) (data *admin.LouPan, err error) {

	var account *admin.Account

	var louPanInfo *admin.LouPan

	err = global.OC_DB.Scopes(dao.ParseAccountDao.Parse(claims, global.OC_DB)).First(&account).Error

	if err != nil {
		return nil, errors.New("无该账号信息")
	}

	res := global.OC_DB.Scopes(dao.LouPanDao.LouPanPreload(global.OC_DB)).First(&louPanInfo, id)

	if res.Error != nil {
		return nil, errors.New("未知错误500")
	}

	if res.RowsAffected == 0 {
		return nil, errors.New("楼盘信息不存在")
	}

	match, err := regexp.MatchString(fmt.Sprintf("(%v)", account.RegionLink), louPanInfo.RegionLink)

	if !match {
		return nil, errors.New("你无权编辑该楼盘")
	}

	louPanInfo.SellLouPanInfo.SellPhone = global.OC_CONFIG.Phone.Account + "-" + louPanInfo.SellLouPanInfo.SellPhone

	return louPanInfo, nil
}

func (*LouPan) Delete(ids []int, claims tools.BaseClaims) (err error) {

	account, err := base.FindAccount(claims, global.OC_DB)
	if err != nil {
		return errors.New(e.AccountNotExist)
	}
	var lous []*admin.LouPan
	global.OC_DB.Preload("SellLouPanInfo").Find(&lous, ids)
	if res := utils.IsThisLouBelongThisAccount(lous, account.RegionLink); !res {
		return errors.New(e.NoRightToOpera)
	}
	err = global.OC_DB.Transaction(func(tx *gorm.DB) error {
		if err = tx.Model(&admin.LouPan{}).Unscoped().Delete(&lous).Error; err != nil {
			return errors.New(e.LouPanDeleteFail)
		}
		var phones []uint
		for _, v := range lous {
			if v.SellLouPanInfo.SellPhone != "" {
				var phone, _ = strconv.ParseUint(v.SellLouPanInfo.SellPhone, 10, 64)
				phones = append(phones, uint(phone))
			}
		}
		if err = loupan_dao.Delete400Phone(tx, phones); err != nil {
			return err
		}
		// 删除分机号
		return nil
	})

	return err

}

var LouPanService = new(LouPan)
